#include<bits/stdc++.h> 
using namespace std;
//	假设一个银行有K个窗口提供服务，一根黄线将等待区域分成两个部分。所有的顾客
//	都必须在黄线之后排成一排，直到窗口有空且他可以被服务了。假设没有一个顾客能
//	单独占用窗口一个小时。现在提供每个顾客的到达时间T和业务处理时间P，需要求得
//	所有顾客的平均等待时间
//1.每个输入都包含一个测试用例，每个测试用例由两部分组成。第一行是由两个正整数
//	N≤10000、K≤100组成的，分别表示顾客总数和窗口总数 
//2.随后N行，每一行包含两个时间，第一个是HH:MM:SS格式的时间，表示到达时间，另
//	一个是单位为分的P，表示业务处理时间。其中HH∈[00,23]，MM和SS∈[00,59]。确保
//	输入内没有两个相同时间到达的顾客
//3.银行工作时间是8:00到17:00，每个早到的人都得等到8:00才行，那些晚到的人不会被
//	计入平均数
//4.对于每个测试用例，需要输出平均等待时间，单位为分，且保留一位小数
//5.struct，运算符重载，queue
struct Customer{	//顾客结构体，包含一个id，到达时间、开始时间、花费时间，时间都是以秒为单位的 
	int id;
	int arrive;
	int spend;
	int start=0;
	bool operator < (const Customer& b) const{
		return arrive<b.arrive;
	}	//重载运算符使得在set中可以直接排序 
};
int main(){
	int N,K;
	cin>>N>>K;
	queue<int> windows[K];	//K个窗口对应K个队列，实际上这道题可以不用队列来表示黄线内区域，因为只有一个人的位置 
	queue<int> allWait;	//所有人排成一队，等待放行 
	map<int,Customer> allCusts;	//id与顾客类一一映射 
	set<Customer> custs;	//用set对顾客类按照到达时间排序 
	int count_ = 0;	//用于计数参与求平均的符合条件的顾客数量 
	for(int i =0;i<N;i++){
		int sp;
		int hh,mm,ss;
		scanf("%d:%d:%d %d",&hh,&mm,&ss,&sp);	//按照这个格式读入数据 
		if(hh>=17) continue;	//如果17点以后到的都砍掉 
		if(sp>60) sp=60;	//如果办理业务超过60分钟的全部按60分钟计算 
		Customer cust;	 
		cust.spend = sp*60; 
		cust.arrive = hh*3600+mm*60+ss;
		custs.insert(cust);	//向set中插入顾客对象 
		count_++;	//累加 
	}
	set<Customer>::iterator it;	//遍历顾客Set 
	int id_ = 0;
	for(it=custs.begin();it!=custs.end();it++){
		Customer cus = (*it);
		cus.id = id_;	//按照顺序发号，用数字代替对象可以节约空间 
		allWait.push(cus.id);	//向总队伍中按照先来后到的顺序插入id 
		allCusts[cus.id] = cus;	//插入映射关系 
		id_++;
	}

	if(count_<=K){	//如果来的人小于窗口数，则所有开门后来的人都不需要等待，只有早到的要等待 
		int sum_=0;
		for(int i=0;i<count_;i++){	//根据先前的计数 
			Customer cus = allCusts[allWait.front()];	//从map中找到id对应的对象 
			if(cus.arrive<28800){	//如果这个人是早到的，那就要计算在门口等开门的时间 
				sum_ += ((28800)-cus.arrive);
			}
			allWait.pop();	//然后这个人可以弹出去了 
		}
		if(count_==0) cout<<"0.0"<<endl;	//如果没有符合情况的人，就输出0.0避免报错nan 
		else printf("%.1f\n",(sum_/(count_*60.0)));	//否则，以分为单位输出平均数，后面那种情况也是同理 
	}
	else{	//如果来的人比窗口数多，则需要进行更新换代的操作 
		int time=28800;	//8点开门 
		for(int i =0;i<K;i++){	//先把K个窗口填满再说 
			Customer cus = allCusts[allWait.front()];
			if(cus.arrive>28800) cus.start = cus.arrive;	//如果这个人是8点以后到的，则开始时间为到的时间 
			else cus.start = 28800;	//	否则，8点开门就8点开始办理业务 
			windows[i].push(cus.id);	//向窗口中添加顾客 
			allWait.pop();	//总队伍中弹出去 
			allCusts[cus.id] = cus;	//更新map 
		}
		time = allCusts[windows[0].front()].start;	//真正开始要更新换代的时间是从第一个窗口的那个人到达时间开始的，可以节约运算时间 
		while(!allWait.empty()){	//这里不能做小于17点的判定，否则测试点5过不去。如果有人明明到了17点，但是前面那个人还在办理业务的话，他还得等到前面那个人办完自己再走，就很rz 
			for(int i =0;i<K;i++){
				if(allWait.empty()) break;	//一旦没有在总队伍等待的人了，就证明都赋值完毕了 
				Customer cus = allCusts[windows[i].front()];
				if(cus.start+cus.spend<=time){	//如果当前时间大于等于某个人开始办理业务的时间+需要花费的时间 
					Customer next = allCusts[allWait.front()];	//从总队伍取出下一个人 
					next.start = cus.start+cus.spend;	//下个人开始的时间就是前一个人结束的时间或者自己到达的时间，这得看谁大 
					if(next.start<next.arrive) next.start = next.arrive;
					windows[i].pop();	//办理完的那个就可以走了 
					windows[i].push(next.id);	//新来的这个就坐下来办理了 
					allWait.pop();
					allCusts[next.id] = next;
				}
			}
			time++;
		}
		int sum_ = 0;
		for(int i =0;i<count_;i++){
			Customer cus = allCusts[i];
			int t = cus.start - cus.arrive;	//用到达时间和开始办理的时间做差得到自己等待的时间 
			if(t<0) sum_ -= t;
			else sum_ += t;
		}
		if(count_==0) cout<<"0.0"<<endl;
		else printf("%.1f\n",(sum_/(count_*60.0)));
	}
	return 0;
	
} 

